共通データ¶
時系列データなら何でもよいので、下記のデータを利用した
pl.read_csv() はURLから直接CSVデータをダウンロードできる
https://www.mhlw.go.jp/stf/covid-19/open-data.html
47都道府県ではデータが多すぎて見づらいので、東京・大阪・名古屋のみにする
import polars as pl
url = "https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv"
data = pl.read_csv(url)
# data = data.melt(id_vars="Date") #pandas と同じ melt でも動くけど deprecated
data = data.unpivot(index=["Date"])
data.columns = ["Date", "Prefecture", "Newly confirmed cases"]
data = data.filter(pl.col("Prefecture").is_in(['Tokyo','Osaka','Aichi']))
# polars は何でも str になるので cast が必要
data = data.with_columns(pl.col("Newly confirmed cases").cast(pl.Int64))
data = data.with_columns(pl.col("Date").str.to_date("%Y/%m/%d"))
data[200:210]
| Date | Prefecture | Newly confirmed cases |
|---|---|---|
| date | str | i64 |
| 2020-08-03 | "Tokyo" | 258 |
| 2020-08-04 | "Tokyo" | 309 |
| 2020-08-05 | "Tokyo" | 263 |
| 2020-08-06 | "Tokyo" | 360 |
| 2020-08-07 | "Tokyo" | 461 |
| 2020-08-08 | "Tokyo" | 429 |
| 2020-08-09 | "Tokyo" | 331 |
| 2020-08-10 | "Tokyo" | 197 |
| 2020-08-11 | "Tokyo" | 188 |
| 2020-08-12 | "Tokyo" | 222 |
data_yoko = data.pivot(index="Date",
on="Prefecture",
values="Newly confirmed cases")
# # Pandas と同じ書式でも動くけど deprecated
# data_yoko = data.pivot(index="Date",
# column="Prefecture",
# values="Newly confirmed cases")
data_yoko
| Date | Tokyo | Aichi | Osaka |
|---|---|---|---|
| date | i64 | i64 | i64 |
| 2020-01-16 | 0 | 0 | 0 |
| 2020-01-17 | 0 | 0 | 0 |
| 2020-01-18 | 0 | 0 | 0 |
| 2020-01-19 | 0 | 0 | 0 |
| 2020-01-20 | 0 | 0 | 0 |
| … | … | … | … |
| 2023-05-04 | 994 | 221 | 499 |
| 2023-05-05 | 906 | 252 | 440 |
| 2023-05-06 | 1062 | 282 | 430 |
| 2023-05-07 | 2345 | 863 | 1098 |
| 2023-05-08 | 1331 | 425 | 547 |
高水準作図ライブラリ¶
Seaborn¶
Seaborn は matplotlib のラッパー。データフレームからシンプルな関数で様々なグラフを描画できる
色遣いがきれいで、デフォルトでもカッコよいグラフが描けるのが特徴。
グラフごとに微妙に作法が違っていたりして、使い込むとやや洗練されていない印象を受ける。
足りない部分は matplotlib で調整できる/する必要があるのが、長所でもあり短所でもある。
また、デフォルトでは日本語が文字化けするのが面倒。
# minimum
import seaborn as sns
ax = sns.lineplot(data=data,
x="Date",
y="Newly confirmed cases",
hue="Prefecture")
#practical
import seaborn as sns
import matplotlib.pyplot as plt
# 日本語文字化け対応でフォントを指定する。matplotlib に比べれば楽。
sns.set(font='Meiryo')
# 画像サイズを設定する程度の事で matplotlib を呼ぶのが面倒
# グラフ描画より前に画像サイズを設定する必要があるなど、matplotlib のお作法に縛られる
plt.figure(figsize=[14,4])
# グラフ描画の関数はシンプルでとっつきやすい
ax = sns.lineplot(data=data,
x="Date",
y="Newly confirmed cases",
hue="Prefecture")
ax.set_title("Covid19 日次感染者数")
plt.xticks(rotation=-90)
plt.show()
# plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
Seaborn Object¶
2022年に導入された Seaborn のグラフィック指向インターフェイス。
ざっくり言って、Seaborn で ggplot/plotnine 的な書き方ができるようになる。
minimum¶
seaborn に含まれているので、新たに別ライブラリをインストールしないで済むのは嬉しい
ワンライナーだとかえって複雑に見えて有難味が分からないが……
#minimum
import seaborn.objects as so
so.Plot(data, x="Date", y="Newly confirmed cases", color="Prefecture").add(so.Line())
Practical¶
実務的な設定をしようと思うと見通しが格段に良くなって有難味が分かる。
- pros
- 関数呼び出しのカッコごとに改行してメソッドチェーンすると読みやすい。
- グラフサイズが Seaborn 内で設定できるようになったのが嬉しい(元々できてろよという気もするが…)
- cons
- 依然としてデフォルトでは日本語非対応
- 日本語フォントの設定は matplotlib の rc 設定を弄っており、おまじないレベルだがちょっと面倒くさい。
import seaborn.objects as so
so.Plot(
data, x="Date", y="Newly confirmed cases", color="Prefecture",
).add(
so.Line()
).layout(
size=(14,5)
).label(
title="COVID19 日次感染者数",
x="日付",
y="新規感染者数"
).theme(
{"font.family":"Meiryo"}
)
minimum¶
最小構成ではやはり有難味が分かりにくい
from plotnine import *
# データとプロット対象を指定
g = ggplot(data, aes(x="Date", y="Newly confirmed cases", color="Prefecture"))
# グラフの種類を指定
g += geom_line()
g
Practical¶
実務的にはこれくらいのコードになる
Pros
- 後から要素を次々につなげていくことで
Cons
- パラメータの書き方がかなり癖があって調べながら出ないとよくわからない
- plotnine をワイルドカードインポートするのがR風
#practical
from plotnine import *
from mizani.breaks import date_breaks
from mizani.formatters import date_format
# データとプロット対象を指定
g = ggplot(data, aes(x="Date", y='Newly confirmed cases', color="Prefecture"))
# グラフの種類を指定
g += geom_line()
# 見た目の調整を指定
g += theme(figure_size=(12, 4), text=element_text(family='Meiryo'))
g += theme(axis_text_x=element_text(rotation=-90, hjust=1))
g += labs(x='日付', y="新規感染者数", title="Covid19 日次感染者数")
g += scale_x_datetime(breaks=date_breaks("4 month"), labels=date_format("%Y-%m"))
g #描画
Polars¶
Polars には hvplot を利用した作図関数があり、単純なプロットなら Polars だけで描画できる。
ほかのライブラリをインストールするのが難しい時などに使えそう。
hvplot なのでデフォルトの描画は bokeh になる
minimum¶
#minimum
data_yoko.plot.line()
Practical¶
実用的にはサイズを指定するくらいがせいぜいか?
#practical
data_yoko.plot.line(width=1200, height=450)
hvplot なのでバックエンドを plotly に変える事もできる
#practical
import hvplot
hvplot.extension('plotly')
data_yoko.plot.line(width=1000, height=400)
hvplot なのでバックエンドを matplotlib に変える事もできる
hvplot.extension('matplotlib')
data_yoko.plot.line(width=1200, height=450)
minimum¶
最低限構成で描画してもかなりサマになる。横幅を目いっぱい使うのがPlotly流。
import plotly
# オフラインHTML出力のためのおまじない
plotly.offline.init_notebook_mode(connected=False)
import plotly.express as px
fig = px.line(data,
x = "Date",
y = "Newly confirmed cases",
color= "Prefecture",
)
fig.show()
Practical¶
Plotlyは日本語がそのまま通るのが美点
import plotly.express as px
fig = px.line(data,
x = "Date",
y = "Newly confirmed cases",
color= "Prefecture",
hover_name = "Prefecture",
title = "Covid19 日次感染者数",
width = 1200,
height = 450,
)
fig.show()
minimal¶
Plotly よりちょっと記述多め
import altair as alt
alt.renderers.enable('html') # Notebook の Html保存に必要
alt.Chart(data).mark_line().encode(
x='Date',
y='Newly confirmed cases',
color='Prefecture',
)
Practical¶
- Pros
- 見た目はなかなか格好良い。
- Cons
- 凝ったことをしようとすると
Prefecture:NDate:Tみたいに型情報を指定してあげないといけないのがイマイチ - Plotly ではデフォルトで有効になっているホバーやズームをいちいち設定する必要がある
- 凝ったことをしようとすると
#practical
import altair as alt
alt.renderers.enable('html') #Notebook の Html 保存に必要
zoom = alt.selection_interval(bind='scales')
alt.Chart(data).mark_line().encode(
x='Date',
y='Newly confirmed cases',
color='Prefecture',
strokeDash='Prefecture',
tooltip = [alt.Tooltip('Prefecture:N'),
alt.Tooltip('Date:T'),
alt.Tooltip('Newly confirmed cases:Q')
]
).properties(
width=1000,
height=400
).add_params(
zoom
).interactive()
HvPlot¶
HvPlot は Holoview をバックエンドとする高水準作図API。
Holoview はさらにバックエンドとして matplotlib/plotly/bokeh を選べるのが特徴で、HvPlot も同様。
表示されるグラフはbokeh / plotly で作図されている場合はインタラクティブに操作できる。
あまりよく調査できていないのだが、pandas の plot 関数を置き換えるような使い方をする。 APIは構造的でなく、いまひとつ洗練されていないように見受けられる。
bokeh をバックエンドに使う高水準作図ライブラリはほかに見つけれれていないので、bokeh が好きなら良いかもしれない。
公式ドキュメント¶
import hvplot
import hvplot.polars
# hvplot.extension('bokeh') #デフォルトではbokeh
data_yoko.hvplot.line(x="Date",
y=["Tokyo", "Osaka", "Aichi"],
width=1200,
height=450,
)
import hvplot
import hvplot.polars
hvplot.extension('plotly')
data_yoko.hvplot.line(x="Date",
y=["Tokyo", "Osaka", "Aichi"],
width=1200,
height=450,
)
c:\Kawashima\src\PythonDataVisualization\venv2\Lib\site-packages\panel\io\notebook.py:201: BokehUserWarning: out of range integer may result in loss of precision c:\Kawashima\src\PythonDataVisualization\venv2\Lib\site-packages\panel\io\notebook.py:201: BokehUserWarning: out of range integer may result in loss of precision
# import hvplot
import hvplot.polars
hvplot.extension('matplotlib')
data_yoko.hvplot.line(x="Date",
y=["Tokyo", "Osaka", "Aichi"],
width=1200,
height=450,
)